package com.hzbc.faceattendance.face.alarm;


import com.alibaba.fastjson.JSON;
import com.hzbc.faceattendance.face.HCNetSDK;
import com.hzbc.faceattendance.face.ISAPI;
import com.hzbc.faceattendance.model.AdminUser;
import com.hzbc.faceattendance.model.AttendanceRecord;
import com.hzbc.faceattendance.model.HaiKangDevice;
import com.hzbc.faceattendance.model.WhiteList;
import com.hzbc.faceattendance.service.*;
import com.hzbc.faceattendance.utils.FileUploadUtil;
import com.sun.jna.Pointer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.Date;
import java.util.List;

/**
 * @author jiangxin
 * @create 2022-08-15-18:04
 */
@Slf4j
@Component
public class AlarmDataParse {

    @Autowired
    FileUploadUtil fileUploadUtil;
    @Autowired
    private IWechatPushService wechatPushService;
    @Autowired
    private IHaiKangDeviceService haiKangDeviceService;
    @Autowired
    private IAdminUserService adminUserService;
    @Autowired
    private IWhitelistService whitelistService;
    @Autowired
    private IAttendanceService attendanceRecordService;
    @Autowired
    private ISAPI isapi;
    @Autowired
    private Alarm alarm;

    public void alarmDataHandle(int lCommand, HCNetSDK.NET_DVR_ALARMER pAlarmer, Pointer pAlarmInfo, int dwBufLen, Pointer pUser) {
        log.info("报警事件类型： lCommand:" + Integer.toHexString(lCommand));
        String sTime;
        String MonitoringSiteID;
        //lCommand是传的报警类型
        switch (lCommand) {
//            case HCNetSDK.COMM_UPLOAD_FACESNAP_RESULT: //实时特征抓拍上传
//                log.info("【实时特征抓拍上传】UPLOAD_FACESNAP_Alarm");
//                HCNetSDK.NET_VCA_FACESNAP_RESULT strFaceSnapInfo = new HCNetSDK.NET_VCA_FACESNAP_RESULT();
//                strFaceSnapInfo.write();
//                Pointer pFaceSnapInfo = strFaceSnapInfo.getPointer();
//                pFaceSnapInfo.write(0, pAlarmInfo.getByteArray(0, strFaceSnapInfo.size()), 0, strFaceSnapInfo.size());
//                strFaceSnapInfo.read();
//                log.info("【实时特征抓拍上传】通道号：" + strFaceSnapInfo.struDevInfo.byChannel);
//                String baojingchannel = strFaceSnapInfo.struDevInfo.byIvmsChannel + "";
//                log.info("【实时特征抓拍上传】IVMS通道号：" + baojingchannel);
//
//                byte[] sIpV4 = strFaceSnapInfo.struDevInfo.struDevIP.sIpV4;
//                String ipv4 = String.format("%d.%d.%d.%d",
//                        (sIpV4[0] & 0xFF),
//                        (sIpV4[1] & 0xFF),
//                        (sIpV4[2] & 0xFF),
//                        (sIpV4[3] & 0xFF));
//                log.info("【实时特征抓拍上传】设备IP：" + ipv4);
//                //事件时间
//                int dwYear = (strFaceSnapInfo.dwAbsTime >> 26) + 2000;
//                int dwMonth = (strFaceSnapInfo.dwAbsTime >> 22) & 15;
//                int dwDay = (strFaceSnapInfo.dwAbsTime >> 17) & 31;
//                int dwHour = (strFaceSnapInfo.dwAbsTime >> 12) & 31;
//                int dwMinute = (strFaceSnapInfo.dwAbsTime >> 6) & 63;
//                int dwSecond = (strFaceSnapInfo.dwAbsTime >> 0) & 63;
//
//                String strAbsTime = "" + String.format("%04d", dwYear) +
//                        String.format("%02d", dwMonth) +
//                        String.format("%02d", dwDay) +
//                        String.format("%02d", dwHour) +
//                        String.format("%02d", dwMinute) +
//                        String.format("%02d", dwSecond);
//
//                //人脸属性信息
//                String sFaceAlarmInfo = "Abs时间:" + strAbsTime + ",是否戴口罩：" +
//                        strFaceSnapInfo.struFeature.byMask + ",是否微笑：" + strFaceSnapInfo.struFeature.bySmile;
//                log.info("人脸信息：" + sFaceAlarmInfo);
//                try {
//                    SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");//设置日期格式
//                    String time = df.format(new Date());// new Date()为获取当前系统时间
//                    //人脸图片写文件
////                    FileOutputStream small = new FileOutputStream("./pic/" + time + "small.jpg");
//                    FileOutputStream big = new FileOutputStream("./images/pic/" + time + "big.jpg");
////                    try {
////                        small.write(strFaceSnapInfo.pBuffer1.getByteArray(0, strFaceSnapInfo.dwFacePicLen), 0, strFaceSnapInfo.dwFacePicLen);
////                        small.close();
////                    } catch (IOException ex) {
////                        ex.printStackTrace();
////                    }
//                    try {
//                        big.write(strFaceSnapInfo.pBuffer2.getByteArray(0, strFaceSnapInfo.dwBackgroundPicLen), 0, strFaceSnapInfo.dwBackgroundPicLen);
//                        big.close();
//                    } catch (IOException ex) {
//                        ex.printStackTrace();
//                    }
//                    HaiKangDevice haiKangDevice = haiKangDeviceService.findHaiKangDeviceByID(baojingchannel);
//                    List<AdminUser> onDutyUsers = adminUserService.findOnDutyUsers();
//                    onDutyUsers.forEach(onDutyUser -> {
//                        try {
//                            wechatPushService.sendAbnormalMessage(onDutyUser.getWcOpenId(), "pic/" + time + "big.jpg", "出入警报", haiKangDevice.getName(), 2);
//                        } catch (Exception e) {
//                            log.error("推送微信消息异常");
//                            e.printStackTrace();
//                        }
//                    });
//                } catch (FileNotFoundException ex) {
//                    ex.printStackTrace();
//                }
//                break;

            case HCNetSDK.COMM_SNAP_MATCH_ALARM:    //人脸比对报警
//                log.info("【人脸对比】COMM_SNAP_MATCH_ALARM");
                SimpleDateFormat sf = new SimpleDateFormat("yyyyMMddHHmmss");
                Date date = new Date();
                String newName = sf.format(date);
                HCNetSDK.NET_VCA_FACESNAP_MATCH_ALARM strFaceSnapMatch = new HCNetSDK.NET_VCA_FACESNAP_MATCH_ALARM();
                strFaceSnapMatch.write();
                Pointer pFaceSnapMatch = strFaceSnapMatch.getPointer();
                pFaceSnapMatch.write(0, pAlarmInfo.getByteArray(0, strFaceSnapMatch.size()), 0, strFaceSnapMatch.size());
                strFaceSnapMatch.read();
//                log.info("【人脸对比】通道号：" + strFaceSnapMatch.struSnapInfo.struDevInfo.byChannel);
                String byIvmsChannel = strFaceSnapMatch.struSnapInfo.struDevInfo.byIvmsChannel + "";

//                HCNetSDK.NET_DVR_getPicture(alarm.getlUserID(), strFaceSnapMatch.struSnapInfo.struDevInfo.byChannel, 1, strFaceSnapMatch.struSnapInfo.pBuffer1, strFaceSnapMatch.struSnapInfo.dwSnapFacePicLen);
                HaiKangDevice haiKangDevice = haiKangDeviceService.findHaiKangDeviceByID(byIvmsChannel);
                int enterStatus = "入口".equals(haiKangDevice.getRemark()) ? 1 : 2;//1进入，2离开
                log.info("【人脸对比】IVMS通道：" + haiKangDevice.getName());
//                byte[] renlianIp = strFaceSnapMatch.struSnapInfo.struDevInfo.struDevIP.sIpV4;
//                String renlianIpStr = String.format("%d.%d.%d.%d",
//                        (renlianIp[0] & 0xFF),
//                        (renlianIp[1] & 0xFF),
//                        (renlianIp[2] & 0xFF),
//                        (renlianIp[3] & 0xFF));
//                log.info("【人脸对比】设备IP：" + renlianIpStr);
                float fSimilarity = strFaceSnapMatch.fSimilarity;
                //比对结果，0-保留，1-比对成功，2-比对失败
                int byContrastStatus = (int) strFaceSnapMatch.byContrastStatus;
                log.info("⌚事件数据:{}", JSON.toJSONString(strFaceSnapMatch));
                String biduijieguo = "";
                if (byContrastStatus == 1) {
                    biduijieguo = "比对成功";
                } else if (byContrastStatus == 2) {
                    biduijieguo = "比对失败";

                }
                String sFaceSnapMatchInfo = "事件时间：" + date + "比对结果：" + biduijieguo + ",相似度：" + fSimilarity;
                log.info(sFaceSnapMatchInfo);
//                log.info("【人脸对比】应该存储本次相机拍摄到的本地");
//                String facepictype = strFaceSnapMatch.byPicTransType + "";
//                log.info("【人脸对比】图片类型：" + (facepictype.equals("0") ? "二进制" : "URL"));
//                log.info("【人脸对比】图片长度：" + strFaceSnapMatch.struSnapInfo.dwSnapFacePicLen);
//                log.info("【人脸对比】图片数据strFaceSnapMatch.struSnapInfo.pBuffer1：" + new String(strFaceSnapMatch.struSnapInfo.pBuffer1.getByteArray(0, strFaceSnapMatch.struSnapInfo.dwSnapFacePicLen)));

                String biduiBigPic = new String(strFaceSnapMatch.pSnapPicBuffer.getByteArray(0, strFaceSnapMatch.struSnapInfo.dwSnapFacePicLen));
                log.info("【人脸对比】图片数据：" + biduiBigPic);
                if (strFaceSnapMatch.struSnapInfo.dwSnapFacePicLen > 0) {
                    try {
                        fileUploadUtil.HttpClientDownloader(biduiBigPic, newName + ".jpg", 1);
                        log.info("【人脸对比】，完成存储本次相机拍摄到的照片");
                    } catch (Exception e) {
                        e.printStackTrace();
                        throw new RuntimeException(e);
                    }
                }
                BigDecimal bigDecimal0 = BigDecimal.valueOf(0.00F);
                BigDecimal bigDecimal7 = BigDecimal.valueOf(0.70F);
                BigDecimal bigDecimalF = BigDecimal.valueOf(fSimilarity);
                if (byContrastStatus == 2 && bigDecimal0.compareTo(bigDecimalF) == 0) {  //陌生人报警
                    List<AdminUser> onDutyUsers = adminUserService.findOnDutyUsers();
                    if (onDutyUsers.size() > 0) {
                        onDutyUsers.forEach(onDutyUser -> {
                            try {
                                wechatPushService.sendAbnormalMessage(onDutyUser.getWcOpenId(), "pic/" + newName + ".jpg", "出入警报", haiKangDevice.getName(), 2, enterStatus);
                            } catch (Exception e) {
                                log.error("推送微信消息异常");
                                e.printStackTrace();
                            }
                        });
                    }
                } else if (byContrastStatus == 2 && bigDecimalF.compareTo(bigDecimal0) > 0 && bigDecimalF.compareTo(bigDecimal7) < 0) {
                    log.info("【人脸对比】比对失败:需要保存一个异常未处理的pushMassage和推送模板消息给管理员");

                    List<AdminUser> onDutyUsers = adminUserService.findOnDutyUsers();
                    log.info("【人脸对比】比对失败，查询设备信息,以及找到在岗的管理员");
                    onDutyUsers.forEach(onDutyUser -> {
                        wechatPushService.sendAbnormalMessage(onDutyUser.getWcOpenId(), "pic/" + newName + ".jpg", "比对异常", haiKangDevice.getName(), 1, enterStatus);
                        log.error("【人脸对比】比对失败，推送微信消息结束");

                    });
                } else if (byContrastStatus != 2 && bigDecimalF.compareTo(bigDecimal7) >= 0) {
                    log.info("人员信息:{}", JSON.toJSONString(strFaceSnapMatch.struBlockListInfo.struBlockListInfo.struAttribute));
                    log.info("【人脸对比】比对成功");
                    byte[] byName = strFaceSnapMatch.struBlockListInfo.struBlockListInfo.struAttribute.byName;
                    log.info("【人脸对比】比对成功，姓名：" + new String(byName, StandardCharsets.UTF_8));
                    log.info("【人脸对比】比对成功，姓名：" + new String(byName, StandardCharsets.ISO_8859_1));
                    String whiteName = new String(strFaceSnapMatch.struBlockListInfo.struBlockListInfo.struAttribute.byName);
                    log.info("【人脸对比】比对成功，姓名：" + whiteName);
                    WhiteList whiteList = whitelistService.findByName(whiteName);
                    log.info("【人脸对比】比对成功，查询服务器白名单是否有该用户，如果没有则创建");
                    if (whiteList == null) {
                        log.info("【人脸对比】比对成功，服务器没有该用户，开始创建");
                        whiteList = new WhiteList();
                        whiteList.setName(whiteName);
                        String sexStr = strFaceSnapMatch.struBlockListInfo.struBlockListInfo.struAttribute.bySex + "";
                        if (sexStr.equals("0")) {
                            whiteList.setGender("男");
                        } else if (sexStr.equals("1")) {
                            whiteList.setGender("女");
                        } else {
                            whiteList.setGender("未知");
                        }
                        byte[] byBirthDate = strFaceSnapMatch.struBlockListInfo.struBlockListInfo.struAttribute.byBirthDate;
                        String namestr = new String(byBirthDate);
                        log.info("【人脸对比】比对成功，生日：" + namestr);
                        log.info("【人脸对比】比对成功，生日：" + new String(byBirthDate, StandardCharsets.UTF_8));
                        log.info("【人脸对比】比对成功，生日：" + new String(byBirthDate, StandardCharsets.ISO_8859_1));
                        long birthDate = Long.valueOf(namestr);
                        whiteList.setBirthDate(LocalDate.ofInstant(Instant.ofEpochMilli(birthDate), ZoneId.systemDefault()));
                        Pointer pFDID = strFaceSnapMatch.struBlockListInfo.pFDID;
                        if ("1ABD4F9FF3524107B9FEBE0D794A174A".equals(pFDID.getString(0)))
                            whiteList.setRole(1);
                        else whiteList.setRole(2);
                        whiteList.setCreateTime(date);
                        log.info("【人脸对比】比对成功，这里是想拿相机人脸库的照片作为服务器白名单的照片");
                        if (strFaceSnapMatch.struBlockListInfo.dwPIDLen > 0 && (strFaceSnapMatch.byPicTransType == 1)) {
                            try {
                                String usertouxiang = new String(strFaceSnapMatch.struBlockListInfo.pPID.getByteArray(0, strFaceSnapMatch.struBlockListInfo.dwPIDLen), 0, strFaceSnapMatch.struBlockListInfo.dwPIDLen);
                                fileUploadUtil.HttpClientDownloader(usertouxiang, newName + ".jpg", 0);
                            } catch (Exception e) {
                                throw new RuntimeException(e);
                            }
                        }
                        whiteList.setImagePath(newName + ".jpg");
                        whiteList = whitelistService.save(whiteList);
                        log.info("【人脸对比】比对成功，本地服务器创建白名单成功: {}", JSON.toJSONString(whiteList));
                    }
                    log.info("【人脸对比】比对成功，存储进出记录");
                    String area = (byIvmsChannel != null && Integer.valueOf(byIvmsChannel) > 37) ? "一楼" : "负一楼";
                    AttendanceRecord attendanceRecord = attendanceRecordService.findRecordByNameAndStatus(whiteName, 0);
                    if (attendanceRecord == null) {
                        attendanceRecord = new AttendanceRecord();
                        attendanceRecord.setArea(area);
                        attendanceRecord.setDeviceId(byIvmsChannel);
                        attendanceRecord.setStatus(0);
                        attendanceRecord.setIsEntered(true);
                        attendanceRecord.setEntryTime(date);
                        attendanceRecord.setStayDuration(0L);
                        attendanceRecord.setLocation(haiKangDevice.getName());
                        attendanceRecord.setWhiteList(whiteList);
                    } else {
                        attendanceRecord.setStatus(1);
                        attendanceRecord.setIsEntered(false);
                        attendanceRecord.setExitTime(date);
                        if (attendanceRecord.getEntryTime() != null) {
                            attendanceRecord.setStayDuration(date.getTime() - attendanceRecord.getEntryTime().getTime());
                        }
                    }
                    attendanceRecord.setImagePath("pic/" + newName + ".jpg");
                    attendanceRecordService.save(attendanceRecord);
                    log.info("【人脸对比】比对成功，消息存储成功：{}", JSON.toJSONString(attendanceRecord));
                }
                log.info("【人脸对比】比对业务处理结束");
                break;
            default:
//                log.info("报警类型" + Integer.toHexString(lCommand));
                break;
        }
    }
}